home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / C++ / Frameworks / Sprocket Framework DR2 / Sprocket Framework / UString.cp < prev    next >
Text File  |  1996-06-15  |  15KB  |  787 lines

  1. /*
  2.  
  3.     File:        UString.cp
  4.     Project:    Sprocket Framework 1.1 (DR2), released 6/15/96
  5.     Contains:    String handling utilities
  6.     To Do:        ?
  7.  
  8.     Sprocket Major Contributors:
  9.     ----------------------------
  10.     Dave Falkenburg, producer of Sprocket 1.0
  11.     Bill Hayden,     producer of Sprocket 1.1
  12.     Steve Sisak,     producer of the upcoming Sprocket 2.0
  13.     
  14.     Pete Alexander        Steve Falkenburg    Randy Thelen
  15.     Eric Berdahl        Nitin Ganatra        Chris K. Thomas
  16.     Marshall Clow        Dave Hershey        Leonard Rosenthal
  17.     Tim Craycroft        Dave Mark            Dean Yu
  18.     David denBoer        Gary Powell
  19.     Cameron Esfahani    Jon Summers            Apple Computer, Inc.
  20.         
  21.     Comments, Additions, or Corrections:
  22.     ------------------------------------
  23.     Bill Hayden, Nikol Software <nikol@codewell.com>
  24.  
  25. */
  26.  
  27.  
  28.  
  29. /*****************************************************************************/
  30.  
  31. #ifndef __MEMORY__
  32. #include <Memory.h>
  33. #endif
  34.  
  35. #ifndef __USTRING__
  36. #include "UString.h"
  37. #endif
  38.  
  39. #include "SprocketMacros.h"
  40.  
  41.  
  42. /* These functions should be linked into whatever segment holds main().  This will
  43. ** guarantee that the functions will always be in memory when called.  It is important
  44. ** that they are in memory, because if a pointer is passed in that points into an
  45. ** unlocked handle, the mere fact that the code needs to get loaded may cause the
  46. ** handle that is pointed into to move.  If you stick to these string functions,
  47. ** you will not have to worry about the handle moving when the string function is
  48. ** called.  If you have your own string functions, and you wish the same safety
  49. ** factor, link the string handling code into the same segment as main(), as you
  50. ** do with these string functions.
  51. */
  52.  
  53. static short    gBase;
  54. static Boolean    gHandleChars;
  55.  
  56.  
  57.  
  58. /*****************************************************************************/
  59. /*****************************************************************************/
  60. /*****************************************************************************/
  61.  
  62.  
  63.  
  64. /* Return the length of the c-string.  (Same as strlen, but this function isn't
  65. ** part of the string library.  The entire library may be more than you wish to
  66. ** link into the code segment that holds main, so this (and other) standard
  67. ** library function has been duplicated here. */
  68.  
  69. short    clen(const char *cptr)
  70. {
  71.     short    i;
  72.     
  73. #if qDebug
  74.     if (cptr == nil)
  75.         DebugMessage("\pclen: String is nil");
  76. #endif
  77.     
  78.     for (i = 0; cptr[i]; ++i) {};
  79.     return(i);
  80. }
  81.  
  82.  
  83.  
  84. /*****************************************************************************/
  85.  
  86.  
  87.  
  88. /* Catenate two c-strings. */
  89.  
  90. char    *ccat(char *s1, char *s2)
  91. {
  92.     ccpy(s1 + clen(s1), s2);
  93.     return(s1);
  94. }
  95.  
  96.  
  97.  
  98. /*****************************************************************************/
  99.  
  100.  
  101.  
  102. /* Copy a c-string. */
  103.  
  104. char    *ccpy(char *s1, char *s2)
  105. {
  106.     char    *c1, *c2;
  107.     
  108. #if qDebug
  109.     if (s1 == nil)
  110.         DebugMessage("\pccpy: Destination is nil");
  111.         
  112.     if (s2 == nil)
  113.         DebugMessage("\pccpy: Source is nil");
  114. #endif
  115.  
  116.     c1 = s1;
  117.     c2 = s2;
  118.     while ((*c1++ = *c2++) != 0) {};
  119.     return(s1);
  120. }
  121.  
  122.  
  123.  
  124. /*****************************************************************************/
  125.  
  126.  
  127.  
  128. /* Compare two pascal-strings. */
  129.  
  130. short    pcmp(StringPtr s1, StringPtr s2)
  131. {
  132.     short    i, len;
  133.     char    j;
  134.     
  135. #if qDebug
  136.     if (s1 == nil)
  137.         DebugMessage("\ppcmp: Destination is nil");
  138.         
  139.     if (s2 == nil)
  140.         DebugMessage("\ppcmp: Source is nil");
  141. #endif
  142.  
  143.     if ((len = s1[0]) > s2[0]) len = s2[0];
  144.  
  145.     for (i = 1; i <= len; ++i) {
  146.         j = s1[i] - s2[i];
  147.         if (j) return(j);
  148.     }
  149.  
  150.     return(s1[0] - s2[0]);
  151. }
  152.  
  153.  
  154.  
  155. /*****************************************************************************/
  156.  
  157.  
  158.  
  159. /* Catenate two pascal-strings. */
  160.  
  161. void    pcat(StringPtr d, StringPtr s)
  162. {
  163.     short    i, j;
  164.     
  165. #if qDebug
  166.     if (d == nil)
  167.         DebugMessage("\ppcat: Destination is nil");
  168.         
  169.     if (s == nil)
  170.         DebugMessage("\ppcat: Source is nil");
  171. #endif
  172.  
  173.     if (((j = s[0]) + d[0]) > 255)
  174.         j = 255 - d[0];
  175.             /* Limit dest string to 255. */
  176.  
  177.     for (i = 0; i < j;) d[++d[0]] = s[++i];
  178. }
  179.  
  180.  
  181.  
  182. /*****************************************************************************/
  183.  
  184.  
  185.  
  186. /* Copy a pascal-string. */
  187.  
  188. void    pcpy(StringPtr d, StringPtr s)
  189. {
  190.     short    i;
  191.     
  192. #if qDebug
  193.     if (d == nil)
  194.         DebugMessage("\ppcpy: Destination is nil");
  195.         
  196.     if (s == nil)
  197.         DebugMessage("\ppcpy: Source is nil");
  198. #endif
  199.  
  200.     i = *s;
  201.     do {
  202.         d[i] = s[i];
  203.     } while (i--);
  204. }
  205.  
  206.  
  207.  
  208. /*****************************************************************************/
  209.  
  210.  
  211.  
  212. /* Convert a c-string to a pascal-string. */
  213.  
  214. void    c2p(char *cptr)
  215. {
  216.     char    len;
  217.     
  218. #if qDebug
  219.     if (cptr == nil)
  220.         DebugMessage("\pc2p: String is nil");
  221. #endif
  222.  
  223.     BlockMoveData(cptr, cptr + 1, len = clen(cptr));
  224.     *cptr = len;
  225. }
  226.  
  227.  
  228.  
  229. /*****************************************************************************/
  230.  
  231.  
  232.  
  233. /* Convert a pascal-string to a c-string. */
  234.  
  235. void    p2c(StringPtr cptr)
  236. {
  237.     unsigned char    len;
  238.  
  239. #if qDebug
  240.     if (cptr == nil)
  241.         DebugMessage("\pc2p: String is nil");
  242. #endif
  243.  
  244.     BlockMoveData(cptr + 1, cptr, len = *cptr);
  245.     cptr[len] = 0;
  246. }
  247.  
  248.  
  249.  
  250. /*****************************************************************************/
  251. /*****************************************************************************/
  252. /*****************************************************************************/
  253.  
  254.  
  255.  
  256. /* Catenate a single character multiple times onto the designated string. */
  257.  
  258. void    ccatchr(char *cptr, char c, short count)
  259. {
  260.     ccpychr(cptr + clen(cptr), c, count);
  261. }
  262.  
  263.  
  264.  
  265. /*****************************************************************************/
  266.  
  267.  
  268.  
  269. /* Convert the value into text for the base-10 number and catenate it to
  270. ** the designated string.  The value is assumed to be signed.  If you wish
  271. ** to have an unsigned decimal value, call ccatnum with a base of 10. */
  272.  
  273. void    ccatdec(char *cptr, long v)
  274. {
  275.     ccatnum(cptr + clen(cptr), v, -10);        /* Catenate value base 10, signed. */
  276. }
  277.  
  278.  
  279.  
  280. /*****************************************************************************/
  281.  
  282.  
  283.  
  284. /* Convert the value into text for base-16, format it, and catenate it to the
  285. ** designated string.  ccatnum could be used, since it handles multiple bases,
  286. ** but ccathex allows for additional common formatting and padding of the
  287. ** hex value. */
  288.  
  289. void    ccathex(char *cptr, char padChr, short minApnd, short maxApnd, long v)
  290. {
  291.     char    str[33], *sptr;
  292.     short    len;
  293.  
  294.     cptr += clen(cptr);            /* We're appending, so point to the end of the string. */
  295.     ccpynum(str, v, 16);        /* Generate minimum-digit hex value. */
  296.  
  297.     if ((len = clen(sptr = str)) > maxApnd)
  298.         sptr = str + len - maxApnd;
  299.  
  300.     if ((len = clen(sptr)) < minApnd)
  301.         if (padChr)
  302.             ccatchr(cptr, padChr, (minApnd - len));
  303.                 /* if we have a pad character, and if necessary, pad the string. */
  304.  
  305.     ccat(cptr, sptr);            /* Add the hex digits to the string. */
  306. }
  307.  
  308.  
  309.  
  310. /*****************************************************************************/
  311.  
  312.  
  313.  
  314. /* Convert the value into text for the designated base.  Catenate the text to
  315. ** the designated string. */
  316.  
  317. void    ccatnum(char *cptr, long v, short base)
  318. {
  319.     ccpynum(cptr + clen(cptr), v, base);
  320. }
  321.  
  322.  
  323.  
  324. /*****************************************************************************/
  325.  
  326.  
  327.  
  328. void    ccpychr(char *cptr, char c, short count)
  329. {
  330.     for (;count--; ++cptr) *cptr = c;
  331.     *cptr = 0;
  332. }
  333.  
  334.  
  335.  
  336. /*****************************************************************************/
  337.  
  338.  
  339.  
  340. void    ccpydec(char *cptr, long v)
  341. {
  342.     ccpynum(cptr, v, -10);
  343. }
  344.  
  345.  
  346.  
  347. /*****************************************************************************/
  348.  
  349.  
  350.  
  351. void    ccpyhex(char *cptr, char padChr, short minApnd, short maxApnd, long v)
  352. {
  353.     cptr[0] = 0;
  354.     ccathex(cptr, padChr, minApnd, maxApnd, v);
  355. }
  356.  
  357.  
  358.  
  359. /*****************************************************************************/
  360.  
  361.  
  362.  
  363. void    ccpynum(char *cptr, long v, short base)
  364. {
  365.     pcpynum((StringPtr)cptr, v, base);
  366.     p2c((StringPtr)cptr);
  367. }
  368.  
  369.  
  370.  
  371. /*****************************************************************************/
  372. /*****************************************************************************/
  373. /*****************************************************************************/
  374.  
  375.  
  376.  
  377. long    c2dec(char *cptr, short *charsUsed)
  378. {
  379.     return(c2num(cptr, 10, charsUsed));
  380. }
  381.  
  382.  
  383.  
  384. /*****************************************************************************/
  385.  
  386.  
  387.  
  388. long    c2hex(char *cptr, short *charsUsed)
  389. {
  390.     return(c2num(cptr, 16, charsUsed));
  391. }
  392.  
  393.  
  394.  
  395. /*****************************************************************************/
  396.  
  397.  
  398.  
  399. long    c2num(char *cptr, short base, short *charsUsed)
  400. {
  401.     Boolean    firstDigit;
  402.     short    i, sgn;
  403.     short    c;
  404.     long    val;
  405.  
  406.     sgn = 1;
  407.     for (firstDigit = false, val = 0, i = 0;;) {
  408.         c = cptr[i++];
  409.         if (base == 256) {
  410.             if (!c) break;
  411.             if (c == '\'') {
  412.                 ++i;
  413.                 break;
  414.             }
  415.             val *= base;
  416.             val += c;
  417.             continue;
  418.         }
  419.         if (c == '-') {
  420.             if (firstDigit) break;
  421.             if (sgn == -1)  break;
  422.             sgn = -1;
  423.             continue;
  424.         }
  425.         if (c == '$') {
  426.             if (firstDigit) break;
  427.             base = 16;
  428.             continue;
  429.         }
  430.         if (gHandleChars) {
  431.             if (c == '\'') {
  432.                 if (firstDigit) break;
  433.                 base = 256;
  434.                 continue;
  435.             }
  436.         }
  437.         if ((!firstDigit) && (c == ' ')) continue;
  438.         c -= '0';
  439.         if (c > 16) c -= 7;        /* Make 'A' a 10, etc. */
  440.         if (c > 32) c -= 32;    /* Make lower-case upper-case. */
  441.         if (c < 0) break;
  442.         if (c >= base) break;
  443.         val *= base;
  444.         val += (c * sgn);
  445.         firstDigit = true;
  446.     }
  447.  
  448.     if (charsUsed) *charsUsed = --i;
  449.  
  450.     gBase = base;
  451.     return(val);
  452. }
  453.  
  454.  
  455.  
  456. /*****************************************************************************/
  457.  
  458.  
  459.  
  460. short    GetLastBase(Boolean handleChars)
  461. {
  462.     gHandleChars = handleChars;
  463.     return(gBase);
  464. }
  465.  
  466.  
  467.  
  468. /*****************************************************************************/
  469. /*****************************************************************************/
  470. /*****************************************************************************/
  471.  
  472.  
  473.  
  474. /* Catenate a single character multiple times onto the designated string. */
  475.  
  476. void    pcatchr(StringPtr pptr, char c, short count)
  477. {
  478.     while (count--) pptr[++(pptr[0])] = c;
  479. }
  480.  
  481.  
  482.  
  483. /*****************************************************************************/
  484.  
  485.  
  486.  
  487. void    pcatdec(StringPtr pptr, long v)
  488. {
  489.     pcatnum(pptr, v, -10);
  490. }
  491.  
  492.  
  493.  
  494. /*****************************************************************************/
  495.  
  496.  
  497.  
  498. void    pcathex(StringPtr pptr, char padChr, short minApnd, short maxApnd, long v)
  499. {
  500.     char    str[33];
  501.  
  502.     ccpyhex(str, padChr, minApnd, maxApnd, v);
  503.     c2p(str);
  504.     pcat(pptr, (StringPtr)str);
  505. }
  506.  
  507.  
  508.  
  509. /*****************************************************************************/
  510.  
  511.  
  512.  
  513. long    pcatnum(StringPtr pptr, long v, short base)
  514. {
  515.     unsigned long    j, vv;
  516.  
  517.     vv = v;
  518.     if (base < 0) {
  519.         base = -base;
  520.         if (v < 0) {
  521.             pptr[++*pptr] = '-';
  522.             vv = -vv;
  523.         }
  524.     }
  525.     j = 0;
  526.     if (vv >= base)
  527.         j = pcatnum(pptr, vv / base, base);
  528.  
  529.     pptr[++*pptr] = "0123456789ABCDEF"[vv - j];
  530.     return(base * vv);
  531. }
  532.  
  533.  
  534.  
  535. /*****************************************************************************/
  536.  
  537.  
  538.  
  539. void    pcpychr(StringPtr pptr, char c, short count)
  540. {
  541.     pptr[0] = 0;
  542.     pcatchr(pptr, c, count);
  543. }
  544.  
  545.  
  546.  
  547. /*****************************************************************************/
  548.  
  549.  
  550.  
  551. void    pcpydec(StringPtr pptr, long v)
  552. {
  553.     *pptr = 0;
  554.     pcatdec(pptr, v);
  555. }
  556.  
  557.  
  558.  
  559. /*****************************************************************************/
  560.  
  561.  
  562.  
  563. void    pcpynum(StringPtr pptr, long v, short base)
  564. {
  565.     *pptr = 0;
  566.     pcatnum(pptr, v, base);
  567. }
  568.  
  569.  
  570.  
  571. /*****************************************************************************/
  572.  
  573.  
  574.  
  575. void    pcpyhex(StringPtr pptr, char padChr, short minApnd, short maxApnd, long v)
  576. {
  577.     *pptr = 0;
  578.     pcathex(pptr, padChr, minApnd, maxApnd, v);
  579. }
  580.  
  581.  
  582.  
  583. /*****************************************************************************/
  584.  
  585.  
  586.  
  587. long    p2dec(StringPtr pptr, short *charsUsed)
  588. {
  589.     return(p2num(pptr, 10, charsUsed));
  590. }
  591.  
  592.  
  593.  
  594. /*****************************************************************************/
  595.  
  596.  
  597.  
  598. long    p2hex(StringPtr pptr, short *charsUsed)
  599. {
  600.     return(p2num(pptr, 16, charsUsed));
  601. }
  602.  
  603.  
  604.  
  605. /*****************************************************************************/
  606.  
  607.  
  608.  
  609. long    p2num(StringPtr pptr, short base, short *charsUsed)
  610. {
  611.     long    val;
  612.  
  613.     p2c(pptr);
  614.     val = c2num((char *)pptr, base, charsUsed);
  615.     c2p((char *)pptr);
  616.     return(val);
  617. }
  618.  
  619.  
  620.  
  621. /*****************************************************************************/
  622. /*****************************************************************************/
  623. /*****************************************************************************/
  624.  
  625.  
  626.  
  627. short    GetHexByte(char *cptr)
  628. {
  629.     short    val, i, chr;
  630.  
  631.     for (val = 0, i = 0; i < 2; ++i) {
  632.         chr = cptr[i];
  633.         if (chr == '=') return(cptr[++i]);
  634.         if (chr == '≈') {
  635.             chr = cptr[++i];
  636.             if ((chr >= 'a') && (chr <= 'z')) chr -= 32;
  637.             return(chr);
  638.         }
  639.         if (chr > 'F')
  640.             chr -= 0x20;
  641.         if (chr > '9')
  642.             chr -= ('A' - '9' - 1);
  643.         val = (val << 4) + chr - '0';
  644.     }
  645.     return(val);
  646. }
  647.  
  648.  
  649.  
  650. /*****************************************************************************/
  651.  
  652.  
  653.  
  654. Boolean    EqualHandle(void *h1, void *h2)
  655. {
  656.     long    s1, s2;
  657.     Ptr        p1, p2;
  658.  
  659.     if ((h1) && (!h2)) return(false);
  660.     if ((h2) && (!h1)) return(false);
  661.     if ((s1 = GetHandleSize((Handle)h1)) != (s2 = GetHandleSize((Handle)h2))) return(false);
  662.  
  663.     p1 = *(Handle)h1;
  664.     p2 = *(Handle)h2;
  665.     for (s1 = 0; s1 < s2; ++s1)
  666.         if (p1[s1] != p2[s1]) return(false);
  667.         
  668.     return(true);
  669. }
  670.  
  671.  
  672.  
  673. /*****************************************************************************/
  674.  
  675.  
  676.  
  677. Boolean    EqualData(void *v1, void *v2, long size)
  678. {
  679.     Ptr        p1, p2;
  680.     long    ii;
  681.  
  682.     if ((v1) && (!v2)) return(false);
  683.     if ((v2) && (!v1)) return(false);
  684.  
  685.     p1 = (Ptr)v1;
  686.     p2 = (Ptr)v2;
  687.     for (ii = 0; ii < size; ++ii)
  688.         if (p1[ii] != p2[ii]) return(false);
  689.         
  690.     return(true);
  691. }
  692.  
  693.  
  694.  
  695. /*****************************************************************************/
  696.  
  697.  
  698.  
  699. void    SetMem(void *vptr, unsigned char c, unsigned long len)
  700. {
  701.     Ptr    ptr;
  702.  
  703.     ptr = (Ptr)vptr;
  704.     while (len--) *ptr++ = c;
  705. }
  706.  
  707.  
  708.  
  709. /*****************************************************************************/
  710.  
  711.  
  712.  
  713. OSErr SetIndString(StringPtr theStr, short resID, short strIndex)
  714. {
  715.     Handle theRes;               /* handle pointing to STR# resource */
  716.     short numStrings;            /* number of strings in STR# */
  717.     short ourString;             /* counter to index up to strIndex */
  718.     char *resStr;                /* string pointer to STR# string to replace */
  719.     long oldSize;                /* size of STR# resource before call */
  720.     long newSize;                /* size of STR# resource after call */
  721.     unsigned long offset;        /* resource offset to str to replace*/
  722.  
  723.     // make sure index is in bounds
  724.  
  725.     if (resID < 1)
  726.         return -1;
  727.  
  728.     // make sure resource exists
  729.  
  730.     theRes = GetResource('STR#', resID);
  731.     if (ResError()!=noErr)
  732.         return ResError();
  733.         
  734.     if (!theRes || !(*theRes))
  735.         return resNotFound;
  736.  
  737.     HLock(theRes);
  738.     HNoPurge(theRes);
  739.  
  740.     // get # of strings in STR#
  741.  
  742.     BlockMoveData(*theRes, &numStrings, sizeof(short));
  743.     if (strIndex > numStrings)
  744.         return resNotFound;
  745.  
  746.     // get a pointer to the string to replace
  747.  
  748.     offset = sizeof(short);
  749.     resStr = (char *) *theRes + sizeof(short);
  750.     for (ourString=1; ourString<strIndex; ourString++)
  751.            {
  752.         offset += 1+resStr[0];
  753.         resStr += 1+resStr[0];
  754.         }
  755.  
  756.     // grow/shrink resource handle to make room for new string
  757.  
  758.     oldSize = GetHandleSize(theRes);
  759.     newSize = oldSize - resStr[0] + theStr[0];
  760.     HUnlock(theRes);
  761.     SetHandleSize(theRes,newSize);
  762.     if (MemError()!=noErr)
  763.         {
  764.         ReleaseResource(theRes);
  765.         return -1;
  766.         }
  767.  
  768.     HLock(theRes);
  769.     resStr = *theRes + offset;
  770.  
  771.     // move old data forward/backward to make room
  772.  
  773.     BlockMoveData(resStr+resStr[0]+1, resStr+theStr[0]+1, oldSize-offset-resStr[0]-1);
  774.  
  775.     // move new data in
  776.  
  777.     BlockMoveData(theStr, resStr, theStr[0]+1);
  778.  
  779.     // write resource out
  780.  
  781.     ChangedResource(theRes);
  782.     WriteResource(theRes);
  783.     HPurge(theRes);
  784.     ReleaseResource(theRes);
  785.  
  786.     return ResError();
  787. }